home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 003 / _gs / !GS / c / GXHT < prev    next >
Text File  |  1991-10-26  |  9KB  |  258 lines

  1. /* Copyright (C) 1989, 1990 Aladdin Enterprises.  All rights reserved.
  2.    Distributed by Free Software Foundation, Inc.
  3.  
  4. This file is part of Ghostscript.
  5.  
  6. Ghostscript is distributed in the hope that it will be useful, but
  7. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  8. to anyone for the consequences of using it or for whether it serves any
  9. particular purpose or works at all, unless he says so in writing.  Refer
  10. to the Ghostscript General Public License for full details.
  11.  
  12. Everyone is granted permission to copy, modify and redistribute
  13. Ghostscript, but only under the conditions described in the Ghostscript
  14. General Public License.  A copy of this license is supposed to have been
  15. given to you along with Ghostscript so you can know your rights and
  16. responsibilities.  It should be in a file named COPYING.  Among other
  17. things, the copyright notice and this notice must be preserved on all
  18. copies.  */
  19.  
  20. /* gxht.c */
  21. /* Halftone rendering routines for Ghostscript imaging library */
  22. #include "memory_.h"
  23. #include "gx.h"
  24. #include "gserrors.h"
  25. #include "gxfixed.h"            /* ditto */
  26. #include "gxmatrix.h"            /* for gxdevice.h */
  27. #include "gxbitmap.h"
  28. #include "gzstate.h"
  29. #include "gzdevice.h"
  30. #include "gzcolor.h"            /* requires gxdevice.h */
  31. #include "gzht.h"
  32.  
  33. /*
  34.  * We don't want to remember all the values of the halftone screen,
  35.  * because they would take up space proportional to P^3, where P is
  36.  * the number of pixels in a cell.  Instead, we pick some number N of
  37.  * patterns to cache.  Each cache slot covers a range of (P+1)/N
  38.  * different gray levels: we "slide" the contents of the slot back and
  39.  * forth within this range by incrementally adding and dropping 1-bits.
  40.  * N>=0 (obviously); N<=P+1 (likewise); also, so that we can simplify things
  41.  * by preallocating the bookkeeping information for the cache, we define
  42.  * a constant max_cached_tiles which is an a priori maximum value for N.
  43.  *
  44.  * Note that the raster for each tile must be a multiple of 32 bits,
  45.  * to satisfy the copy_mono device routine, even though a multiple of
  46.  * 16 bits would otherwise be sufficient.
  47.  */
  48. #define max_cached_tiles 25
  49. typedef struct bit_tile_s {
  50.     int level;            /* the cached gray level, i.e. */
  51.                     /* the number of spots whitened, */
  52.                     /* or -1 if the cache is empty */
  53.     gx_bitmap tile;            /* the currently rendered tile */
  54. } bit_tile;
  55. typedef struct gx_ht_cache_s {
  56.     /* The following are set when the cache is created. */
  57.     byte *bits;            /* the base of the bits */
  58.     uint bits_size;            /* the space available for bits */
  59.     /* The following are reset each time the cache is initialized */
  60.     /* for a new screen. */
  61.     ht_bit *order;            /* the cached order vector */
  62.     int num_cached;            /* actual # of cached tiles */
  63.     int levels_per_tile;        /* # of levels per cached tile */
  64.     bit_tile tiles[max_cached_tiles];    /* the cached tiles */
  65. } ht_cache;
  66. private ht_cache cache;
  67. #define max_ht_bits 1000        /* arbitrary, maybe too small */
  68. private byte cache_bits[max_ht_bits];
  69. /* Bit masks for whitening vector.  We have to initialize these */
  70. /* indirectly, because they are different for big- and little-endian */
  71. /* machines. */
  72. typedef unsigned short bit16;
  73. private byte single_bits8[16*2] =
  74.    {    0x80,0, 0x40,0, 0x20,0, 0x10,0, 8,0, 4,0, 2,0, 1,0,
  75.     0,0x80, 0,0x40, 0,0x20, 0,0x10, 0,8, 0,4, 0,2, 0,1
  76.    };
  77. #define single_bits ((bit16 *)single_bits8)
  78. private byte mb1[2] =
  79.    {    0xff,0xff };
  80. private byte mb2[4] =
  81.    {    0xaa,0xaa, 0x55,0x55 };
  82. private byte mb3[6] =
  83.    {    0x92,0x49, 0x49,0x24, 0x24,0x92 };
  84. private byte mb4[8] =
  85.    {    0x88,0x88, 0x44,0x44, 0x22,0x22, 0x11,0x11 };
  86. private byte mb5[10] =
  87.    {    0x84,0x21, 0x42,0x10, 0x21,0x08, 0x10,0x84, 0x08,0x42 };
  88. private byte mb6[12] =
  89.    {    0x82,0x08, 0x41,0x04, 0x20,0x82, 0x10,0x41, 0x08,0x20, 0x04,0x10 };
  90. private byte mb7[14] =
  91.    {    0x81,0x02, 0x40,0x81, 0x20,0x40, 0x10,0x20, 0x08,0x10, 0x04,0x08,
  92.         0x02,0x04
  93.    };
  94. private byte mb8[16] =
  95.    {    0x80,0x80, 0x40,0x40, 0x20,0x20, 0x10,0x10, 0x08,0x08, 0x04,0x04,
  96.         0x02,0x02, 0x01,0x01
  97.    };
  98. private bit16 *multi_bits[9] =
  99.    {    0, (bit16 *)mb1, (bit16 *)mb2, (bit16 *)mb3, (bit16 *)mb4,
  100.     (bit16 *)mb5, (bit16 *)mb6, (bit16 *)mb7, (bit16 *)mb8
  101.    };
  102.  
  103. /* Construct the order vector.  order is an array of ht_bits: */
  104. /* order[i].offset contains the index of the bit position */
  105. /* that is i'th in the whitening order. */
  106. int
  107. gx_ht_construct_order(ht_bit *order, int width, int height)
  108. {    uint i;
  109.     uint size = (uint)(width * height);
  110.     int padding = (-width) & 31;
  111.     if ( (width + padding) / 8 * height > max_ht_bits )
  112.         return_error(gs_error_limitcheck);    /* can't cache the rendering */
  113.     /* Clear the cache, to avoid confusion in case */
  114.     /* the address of a new order vector matches that of a */
  115.     /* (deallocated) old one. */
  116.     cache.order = NULL;
  117.     cache.bits = cache_bits;
  118.     cache.bits_size = max_ht_bits;
  119.     /* Convert sequential indices to */
  120.     /* byte indices and mask values. */
  121.     for ( i = 0; i < size; i++ )
  122.        {    int pix = order[i].offset;
  123.         pix += pix / width * padding;
  124.         order[i].offset = (pix >> 4) << 1;
  125.         order[i].mask =
  126.             (width <= 8 ?
  127.              multi_bits[width][pix & 15] :
  128.              single_bits[pix & 15]);
  129.        }
  130. #ifdef DEBUG
  131. if ( gs_debug['h'] )
  132.        {    dprintf1("[h]Halftone order %lx:\n", (ulong)order);
  133.         for ( i = 0; i < size; i++ )
  134.             dprintf3("%4d: %u:%x\n", i, order[i].offset,
  135.                  order[i].mask);
  136.        }
  137. #endif
  138.     return 0;
  139. }
  140.  
  141. /* Load the device color into the halftone cache if needed. */
  142. private void render_ht(P3(bit_tile *, int, halftone *));
  143. private void init_ht(P2(ht_cache *, halftone *));
  144. void
  145. gx_color_load(gx_device_color *pdevc, gs_state *pgs)
  146. {    int level = pdevc->halftone_level;
  147.     halftone *pht;
  148.     bit_tile *bt;
  149.     if ( level == 0 ) return;    /* no halftone */
  150.     pht = pgs->halftone;
  151.     if ( cache.order != pht->order )
  152.         init_ht(&cache, pht);
  153.     bt = &cache.tiles[level / cache.levels_per_tile];
  154.     if ( bt->level != level )
  155.         render_ht(bt, level, pht);
  156.     pdevc->tile = &bt->tile;
  157. }
  158.  
  159. /* Initialize the tile cache for a given screen. */
  160. /* Cache as many different levels as will fit. */
  161. private void
  162. init_ht(ht_cache *pcache, halftone *pht)
  163. {    int width = pht->width;
  164.     int height = pht->height;
  165.     int size = width * height;
  166.     static int up_to_16[] =
  167.         /* up_to_16[i] = 16 / i * i */
  168.         { 0, 16, 16, 15, 16, 15, 12, 14, 16 };
  169.     int width_unit = (width <= 8 ? up_to_16[width] : width);
  170.     uint raster = ((width + 31) >> 5) << 2;
  171.     uint tile_bytes = raster * height;
  172.     int num_cached;
  173.     int i;
  174.     byte *tbits = pcache->bits;
  175.     /* Make sure num_cached is within bounds */
  176.     num_cached = max_ht_bits / tile_bytes;
  177.     if ( num_cached > size ) num_cached = size;
  178.     if ( num_cached > max_cached_tiles ) num_cached = max_cached_tiles;
  179.     for ( i = 0; i < num_cached; i++ )
  180.        {    register bit_tile *bt = &pcache->tiles[i];
  181.         bt->level = -1;
  182.         bt->tile.data = tbits;
  183.         bt->tile.raster = raster;
  184.         bt->tile.width = width_unit;
  185.         bt->tile.height = height;
  186.         tbits += tile_bytes;
  187.        }
  188.     pcache->order = pht->order;
  189.     pcache->num_cached = num_cached;
  190.     pcache->levels_per_tile = (size + num_cached - 1) / num_cached;
  191. }
  192.  
  193. /*
  194.  * Compute and save the rendering of a given gray level
  195.  * with the current halftone.  The cache holds multiple tiles,
  196.  * where each tile covers a range of possible levels.
  197.  * If the tile whose range includes the desired level is already loaded,
  198.  * we adjust it incrementally: this saves a lot of time for
  199.  * the average image, where gray levels don't change abruptly.
  200.  * Note that we will never be asked to cache levels 0 or order_size,
  201.  * which correspond to black or white respectively.
  202.  */
  203. private void
  204. render_ht(bit_tile *pbt, int level /* [1..order_size-1] */, halftone *pht)
  205. {    ht_bit *order = pht->order;
  206.     register ht_bit *p;
  207.     register ht_bit *endp;
  208.     register byte *bits = pbt->tile.data;
  209.     int old_level = pbt->level;
  210.     if ( old_level < 0 )
  211.        {    /* The cache is empty.  Preload it with */
  212.         /* whichever of all-0s and all-1s will be faster. */
  213.         uint tile_bytes = pbt->tile.raster * pbt->tile.height;
  214.         if ( level >= pht->order_size >> 1 )
  215.            {    old_level = pht->order_size;
  216.             memset(bits, 0xff, tile_bytes);
  217.            }
  218.         else
  219.            {    old_level = 0;
  220.             memset(bits, 0, tile_bytes);
  221.            }
  222.        }
  223. #ifdef DEBUG
  224.     if ( level < 0 || level > pht->order_size || level == old_level )
  225.        {    lprintf3("Error in render_ht: level=%d, old_level=%d, order_size=%d=n", level, old_level, pht->order_size);
  226.         gs_exit(1);
  227.        }
  228. #endif
  229.     /* Note that we can use the same loop to turn bits either */
  230.     /* on or off, using xor.  We use < to compare pointers, */
  231.     /* rather than ==, because Turbo C only compares the */
  232.     /* low 16 bits for < and > but compares all 32 bits for ==. */
  233.     if ( level > old_level )
  234.         p = &order[old_level], endp = &order[level];
  235.     else
  236.         p = &order[level], endp = &order[old_level];
  237.     /* Invert bits between the two pointers */
  238.     do
  239.        {    *(bit16 *)&bits[p->offset] ^= p->mask;
  240.        }
  241.     while ( ++p < endp );
  242. #ifdef DEBUG
  243. if ( gs_debug['h'] )
  244.        {    byte *p = bits;
  245.         int wb = pbt->tile.raster;
  246.         byte *ptr = bits + wb * pbt->tile.height;
  247.         dprintf7("[h]Halftone cache %lx: old=%d, new=%d, w=%d(%d), h=%d(%d):\n",
  248.              (ulong)bits, old_level, level, pbt->tile.width,
  249.                  pht->width, pbt->tile.height, pht->height);
  250.         while ( p < ptr )
  251.            {    dprintf1(" %02x", *p++);
  252.             if ( (p - bits) % wb == 0 ) dputc('\n');
  253.            }
  254.        }
  255. #endif
  256.     pbt->level = level;
  257. }
  258.